﻿using Coolzon.Common;
using Coolzon.Realtime.Contracts;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace Coolzon.UI.Common.RealtimeProxies
{
    /// <summary>
    /// 连接服务器的代理接口的管理类
    /// </summary>
    public class RealtimeProxyManager
    {
        public const string EVENTBUS_FLAGNAME = "NET";

        private static RealtimeProxyManager s_instance = new RealtimeProxyManager();

        public static RealtimeProxyManager Instance
        {
            get
            {
                return s_instance;
            }
        }

        public ResponseKeeperV2 ResponseKeeper = new ResponseKeeperV2();

        private List<RealtimeProxy> _clientList;

        /// <summary>
        /// 获取主服务代理列表
        /// </summary>
        public List<RealtimeProxy> Proxies
        {
            get
            {
                return _clientList;
            }
        }

        /// <summary>
        /// 最后一次发送请求的时间
        /// </summary>
        private long _latestSendTicks;
        /// <summary>
        /// 发送间隔，小于这个时间无法发送
        /// </summary>
        private long _sendInterval = TimeSpan.FromSeconds(1).Ticks;

        #region main server client

        /// <summary>
        /// 初始化客户端代理对象列表
        /// </summary>
        /// <param name="callbackImplement"></param>
        /// <returns>true:初始化之后，有连接成功,false:初始化之后，没有连接成功的</returns>
        public bool InitClientProxyList(Endpoint[] endpoints, IMainServiceCallback callbackImplement)
        {
            bool isClientOpened = false;
            if (_clientList == null)
            {
                _clientList = new List<RealtimeProxy>();
            }
            else
            {
                // 关闭已有的连接
                for (int index = 0; index < _clientList.Count; index++)
                {
                    try
                    {
                        if (_clientList[index].Client.State == CommunicationState.Opened)
                        {
                            _clientList[index].Client.Close();
                        }
                    }
                    catch
                    {
                    }
                }
                _clientList.Clear();
            }

                // 添加备用服务器信息
            for (int index = 0; index < endpoints.Length; index++)
            {
                _clientList.Add(new RealtimeProxy(endpoints[index], callbackImplement));
            }

            for (int index = 0; index < _clientList.Count; index++)
            {
                try
                {
                    _clientList[index].Client.Open();

                    _clientList[index].State = ServiceProxyState.Connected;
                    isClientOpened = true;
                }
                catch
                {
                }
            }
            return isClientOpened;
        }

        /// <summary>
        /// 不检查请求发送的时间间隔
        /// </summary>
        /// <param name="request"></param>
        public void SendRequestSys(Request request)
        {
            SendRequestCore(request);
        }
        /// <summary>
        /// 不检查请求发送的时间间隔
        /// </summary>
        /// <param name="domainId"></param>
        /// <param name="userIdentity"></param>
        /// <param name="scenario"></param>
        /// <param name="command"></param>
        /// <param name="mode"></param>
        /// <param name="requestData"></param>
        public void SendRequestSys(string domainId, string userIdentity, byte scenario, byte command, byte mode, object requestData)
        {
            Request request = RequestUtil.BuildRequest(domainId, userIdentity, scenario, command, mode, requestData);
            SendRequestSys(request);
        }

        /// <summary>
        /// 检查时间间隔
        /// </summary>
        /// <param name="request"></param>
        public void SendRequest(Request request)
        {
            long nowTicks = DateTime.Now.Ticks;

            if (nowTicks - _latestSendTicks < _sendInterval)
            {
                //// 发送请求速度过快
                //ModuleMessageEvent message = new ModuleMessageEvent();
                //message.Module = "ServiceProxy";
                //message.ErrorCode = "1";
                //message.Message = "请求发送速度过快";
                //EventBus.Instance.PublishAsync(message);
                Logger.WarningToTag("ServiceProxy", string.Format("请求发送速度过快scenario:{0:X00}, command:{1:X00}",
                    request.Header.Scenario,
                    request.Header.Command));
                return;
            }

            try
            {
                SendRequestCore(request);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                _latestSendTicks = DateTime.Now.Ticks;
            }
        }
        public void SendRequest(string domainId, string userIdentity, byte scenario, byte command, byte mode, object requestData)
        {
            Request request = RequestUtil.BuildRequest(domainId, userIdentity, scenario, command, mode, requestData);
            SendRequest(request);
        }


        /// <summary>
        /// 实际发送指令
        /// </summary>
        /// <param name="request"></param>
        private void SendRequestCore(Request request)
        {
            List<string> serverAddressList = new List<string>();

            int expectantResponseCount = 0;
            for (int index = 0; index < _clientList.Count; index++)
            {
                if (_clientList[index].Client != null && _clientList[index].Client.State == CommunicationState.Opened)
                {
                    expectantResponseCount++;
                    serverAddressList.Add(string.Format("{0}:{1}", _clientList[index].IP, _clientList[index].Port));
                }
            }

            request.Header.ServerAddress = serverAddressList.ToArray();
            // 生成一个随机的唯一标识
            request.Header.UniqueKey = Guid.NewGuid();
            // 设置预期将收到的回应数量
            request.Header.ExpectantResponseCount = expectantResponseCount;

            Logger.DebugToTag("ServiceProxy", string.Format("发送请求,scenario:0x{0:X2}, command:0x{1:X2}, uniqueKey:{2}, expectantResposeCount:{3}",
                request.Header.Scenario,
                request.Header.Command,
                request.Header.UniqueKey,
                request.Header.ExpectantResponseCount));

            ResponseKeeper.Retrive();
            ResponseKeeper.Register(request.Header.UniqueKey, request.Header.ServerAddress, expectantResponseCount);

            for (int index = 0; index < _clientList.Count; index++)
            {
                if (_clientList[index].Client != null && _clientList[index].Client.State == CommunicationState.Opened)
                {
                    try {
                        _clientList[index].Client.BeginSendRequest(request, SendRequestCallback, new object[] { _clientList[index].Client, request });
                    }
                    catch { }
                }
            }
        }
        /// <summary>
        /// 发送指令回调方法
        /// </summary>
        /// <param name="result"></param>
        private void SendRequestCallback(IAsyncResult result)
        {
            object[] obj = (object[])result.AsyncState;
            RealtimeClient mainServiceClient = (RealtimeClient)obj[0];
            Request request = (Request)obj[1];
            try
            {
                mainServiceClient.EndSendRequest(result);
            }
            catch (Exception ex)
            {
                Logger.ErrorToTag("ServiceProxy", string.Format("发送请求,scenario:0x{0:X2}, command:0x{1:X2}, uniqueKey:{2}, expectantResposeCount:{3}失败,ex:{4}",
                    request.Header.Scenario,
                    request.Header.Command,
                    request.Header.UniqueKey,
                    request.Header.ExpectantResponseCount,
                    ex));
            }
        }


        /// <summary>
        /// 获得可用的服务器客户端数量
        /// </summary>
        /// <returns></returns>
        public int GetAvailableMainServiceClientCount()
        {
            int clientCount = 0;
            for (int index = 0; index < _clientList.Count; index++)
            {
                if (_clientList[index].Client.State == CommunicationState.Opened)
                {
                    clientCount++;
                }
            }
            return clientCount;
        }

        #endregion
    }

    //class HostState
    //{
    //    public Endpoint Host { get; set; }
    //    public bool IsOK { get; set; }

    //    public HostState(Endpoint host, bool isOK)
    //    {
    //        this.Host = host;
    //        this.IsOK = isOK;
    //    }
    //}
}
